<?php
/**
 * Inter View层。
 * 把PHP引擎直接当作模版引擎显示法。
 * 本组件依赖性：可独立使用。
 * 本文件的思路参考过以下程序，在此一并致谢！
 *     - PHP框架Punny{@link http://skiyo.cn/punny/}
 *     - PHP框架FleaPHP{@link http://qeephp.com/}
 * 
 * @author Horse Luke<horseluke@126.com>
 * @copyright Horse Luke, 2009
 * @license the Apache License, Version 2.0 (the "License"). {@link http://www.apache.org/licenses/LICENSE-2.0}
 * @version $Id: View.php 115 2010-06-27 11:19:54Z horseluke@126.com $
 * @package Inter_PHP_Framework
 */

class Inter_View{

    /**
     * 存放模版的目录。最后不要以/结尾
     *
     * @var string
     */
    public $tplDir = '';

    /**
     * 模板文件名。
     * 命名规则：
     * 1、首字符必须为0到9、a到z、A到Z、‘-’、‘_’这四种中的其中一个。
     * 2、后面的字符可以是0到9、a到z、A到Z、‘-’、‘_’和‘.’中的其中一个。可重复0个或者多个
     *
     * @var string
     */
    public $tplName = '';

    /**
     * 模版后缀名，方便进行json/xml/htm的数据交换格式交换。看Punny View层突然想到的思路。
     * 命名规则：可以是0到9、a到z、A到Z、‘-’、‘_’和‘.’中的其中一个。可重复0个或者多个
     *
     * @var string
     */
    public $tplSuffix = '.htm';

    //模版变量储存区
    protected $_tVar = array();

    /**
     * 构造方法
     */
    public function __Construct(){
    }

    /**
     * 设置模版的参数
     * 本方法专供新手用，老手可直接用$this->xxx = xxx，但需自行确保参数正确。
     * 此段主要模仿punny view文件
     *
     * @param string $name 参数名称
     * @param string $value 参数值
     * @param bool $check 是否执行正确性检查？默认为true。设置为false将等于$this->xxx = xxx
     */
    public function setOption($name, $value, $check = true){
        switch ($name){
            case 'tplDir':
                //不用realpath解析，改用is_dir判断。
                //$value = (string)realpath($value);
                if( true == $check  && !is_dir($value)){
                    throw new Exception("Template Directory '{$value}' does not exist or is not valid.");
                }
                break;
            case 'tplName':
                //文件名不符合命名规则，则抛出exception
                if( true == $check  && !preg_match('/^[0-9a-zA-Z-_]{1,1}[0-9a-zA-Z-_.]*$/', $value)){
                    throw new Exception("Template Name '{$value}' is Not in conformity with the filename rules.");
                }
                break;
            case 'tplSuffix':
                //文件名后缀不符合命名规则，则抛出exception
                if( true == $check  && !preg_match("/^[0-9a-zA-Z-_.]*$/", $value)){
                    throw new Exception("Template Suffix '{$value}' is Not in conformity with the filename rules.");
                }
                break;
            default:
                $name = $value = "{$name}_notExistOption";     //其它参数直接无视，给个不存在的参数，让其在后面抛出exception
                break;
        }
        $this->$name = $value;
    }
    
    /**
     * 批量设置模版的参数
     *
     * @param array $options 模板参数数组
     * @param bool $check 是否执行正确性检查？默认为true。设置为false将等于$this->xxx = xxx
     */
    public function setOptions( $options, $check = true ){
        foreach ($options as $name => $value){
            $this->setOption($name, $value, $check);
        }
    }

    /**
     * 魔术方法设置值。直接禁止。
     *
     * @param string $name
     * @param mixed $value
     */
    public function __set($name, $value){
        throw new Exception("Sorry but the option '{$name}' can not be found to set.");
    }

    /**
     * 模版变量赋值
     *
     * @param mixed $name 模版的变量名称。假如传入的是数组，必须遵循$key => $value 准则，并且$key要符合变量名称的规则（比如$key不能为数字等）
     * @param mixed $value 对应变量值
     */
    public function assign($name,$value=''){
        if(is_array($name)){
            foreach ($name as $k => $v){
                $this->_tVar[$k] = $v;
            }
        }else{
            $this->_tVar[$name] = $value;
        }
    }

    /**
     * 清空模版赋值的所有内容
     */
    public function resetAssign(){
        $this->_tVar = array();
    }


    /**
     * 模板输出
     *
     * @param string $tplName 模板名称
     * @param string $output 模板的内容是立刻输出，还是只是返回就行？
     * @return string 模板的内容（参数$output为false的时候才有效）
     */
    public function display($tplName = '', $output = true){

        if(!empty($tplName)){
            $this->setOption('tplName',$tplName);
        }
        unset($tplName);

        $tplFilePath = $this->tplDir.DIRECTORY_SEPARATOR. $this->tplName. $this->tplSuffix;
        if(!is_file($tplFilePath)){
            throw new Exception("Template File '{$tplFilePath}' doesn't exist or is inaccessable.");
        }

        extract($this->_tVar, EXTR_SKIP);     //fleaPHP View层思路
        ob_start();
        require ($tplFilePath);
        if( $output == false ){
            $content = ob_get_contents();
            ob_end_clean();
            return $content;
        }else{
            ob_end_flush();
        }
    }

}
